﻿using AutoMapper;
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Cmp;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zocono.Infrastructure.Common;
using Zocono.WCS.Domain.DomainRepository;
using Zocono.WCS.Domain.EntityInfo;
using Zocono.WCS.Infrastructure.ApllicationDto;
using Zocono.WCS.Infrastructure.ApllicationDto.Enums;
using Zocono.WCS.Infrastructure.ApllicationDto.WCSTaskDto;
using Zocono.WCS.WMSApiDomain.WebApi;

namespace Zocono.WCS.Domain.WorkTaskDomain
{
    public class WorkTaskInfoServeice : IWorkTaskInfoServeice
    {
        private readonly ILogUtil _LogUtil;
        private readonly ISnowflake _Sonoflake;
        private readonly IWorkTaskInfoRepository _WorkTaskInfoRepository;
        private readonly IMapper _mapper;

        public WorkTaskInfoServeice(ILogUtil logUtil
            , ISnowflake snowflake
            , IWorkTaskInfoRepository workTaskInfoRepository
            , IMapper mapper)
        {
            _LogUtil = logUtil;
            _Sonoflake = snowflake;
            _WorkTaskInfoRepository = workTaskInfoRepository;
            this._mapper = mapper;
        }



        public async Task<PageDto<WCSWorkTaskInfoDto>> GetPagedCurrentWorkTaskInfoAsync(QueryWorkTaskInfoDto queryWorkTaskInfoDto)
        {
            var exp = Expressionable.Create<WorkTaskInfo, RouteInfo>();
            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.PalletCode), (wti, ri) => wti.PalletCode.Contains(queryWorkTaskInfoDto.PalletCode));
            exp.AndIF(queryWorkTaskInfoDto.TaskCode.HasValue, (wti, ri) => wti.TaskCode == queryWorkTaskInfoDto.TaskCode);

            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.RouteInfo), (wti, ri) => ri.FromStation.Contains(queryWorkTaskInfoDto.RouteInfo) || ri.ToStation.Contains(queryWorkTaskInfoDto.RouteInfo));

            //exp.AndIF(queryWorkTaskInfoDto.TaskProcessState.HasValue, (wti, ri) => wti.TaskProcessState == Enum.Parse<EnumTaskProcessState>(queryWorkTaskInfoDto.TaskProcessState.ToString()));
            if (queryWorkTaskInfoDto.TaskState > 2)
            {
                exp.AndIF(true, (wti, ri) => wti.TaskState == EnumTaskState.Executing || wti.TaskState == EnumTaskState.Initial);
            }
            else if (queryWorkTaskInfoDto.TaskState == null)
            {
                exp.AndIF(true, (wti, ri) => wti.TaskState == EnumTaskState.Executing || wti.TaskState == EnumTaskState.Initial);
            }
            else if (queryWorkTaskInfoDto.TaskState == 2)
            {
                exp.AndIF(true, (wti, ri) => wti.TaskState == EnumTaskState.Executing);
            }
            else if (queryWorkTaskInfoDto.TaskState == 0)
            {
                exp.AndIF(true, (wti, ri) => wti.TaskState == EnumTaskState.Initial);
            }
            else
            {
                exp.AndIF(queryWorkTaskInfoDto.TaskState.HasValue, (wti, ri) => wti.TaskState.ToInt32() == queryWorkTaskInfoDto.TaskState);
            }

            PageDto<WCSWorkTaskInfoDto> pagedData = new PageDto<WCSWorkTaskInfoDto>();
            RefAsync<int> totalCount = 0;

            var result = await _WorkTaskInfoRepository.AsSugarClient()
                .Queryable<WorkTaskInfo, RouteInfo>((wti, ri) => new JoinQueryInfos(JoinType.Inner, wti.RouteID == ri.ID))
                .Where(exp.ToExpression())
                .Select((wti, ri) => new WCSWorkTaskInfoDto()
                {
                    ID = wti.ID,
                    RouteID = wti.RouteID,
                    FromStation = ri.FromStation,
                    ToStation = ri.ToStation,
                    Priority = wti.Priority,
                    PalletCode = wti.PalletCode,
                    TaskCode = wti.TaskCode,
                    TaskProcessState = wti.TaskProcessState,
                    TaskState = wti.TaskState,
                    TaskType = wti.TaskType,
                    SaveTime = wti.SaveTime,
                    UpdateTime = wti.UpdateTime,
                    WmsTaskCode = wti.WmsTaskCode,
                    DependWmsTaskCode = wti.DependWmsTaskCode,
                    WmsFromStation = wti.WmsFromStation,
                    WmsFromPosition = wti.WmsFromPosition.ToString(),
                    WmsToStation = wti.WmsToStation,
                    WmsToPosition = wti.WmsToPosition,
                    CurrentRounteDetailID = wti.CurrentRounteDetailID,
                    CurrentDetailTaskState = wti.CurrentDetailTaskState,
                    CurrentDispatchType = wti.CurrentDispatchType,
                    CurrentFromEquipment = wti.CurrentFromEquipment,
                    CurrentFromCargo = wti.CurrentFromCargo,
                    CurrentToEquipment = wti.CurrentToEquipment,
                    CurrentToCargo = wti.CurrentToCargo,
                    CurrentCreateTime = wti.CurrentCreateTime,
                    CurrentUpdateTime = wti.CurrentUpdateTime,
                    UploadWmsState = wti.UploadWmsState,
                    UploadWmsTime = wti.UploadWmsTime
                })
                .ToPageListAsync(queryWorkTaskInfoDto.PageIndex, queryWorkTaskInfoDto.PageSize, totalCount);

            pagedData.Result = result;
            pagedData.Total = totalCount;

            return pagedData;
        }


        public async Task<PageDto<WCSWorkTaskInfoDto>> GetPagedWorkTaskInfoAsync(QueryWorkTaskInfoDto queryWorkTaskInfoDto)
        {
            var stateUpload = Enum.Parse<EnumUploadWmsState>(queryWorkTaskInfoDto.UploadWmsState.ToString());
            var endTime = queryWorkTaskInfoDto.EndTime.ToDateTimeFormat("yyyy-MM-dd HH:mm");
            var startTime = queryWorkTaskInfoDto.StarTime.ToDateTimeFormat("yyyy-MM-dd HH:mm");
            var exp = Expressionable.Create<WorkTaskInfo, RouteInfo>();
            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.PalletCode), (wti, ri) => wti.PalletCode.Contains(queryWorkTaskInfoDto.PalletCode));
            exp.AndIF(queryWorkTaskInfoDto.TaskCode.HasValue, (wti, ri) => wti.TaskCode == queryWorkTaskInfoDto.TaskCode);
            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.StarTime), (wti, ri) => wti.SaveTime >= startTime);
            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.EndTime), (wti, ri) => wti.SaveTime < endTime);
            exp.AndIF(queryWorkTaskInfoDto.UploadWmsState.HasValue, (wti, ri) => wti.UploadWmsState == stateUpload);
            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.FromStation), (wti, ri) => ri.FromStation.Contains(queryWorkTaskInfoDto.FromStation));
            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.ToStation), (wti, ri) => ri.ToStation.Contains(queryWorkTaskInfoDto.ToStation));
            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.RouteInfo), (wti, ri) => ri.FromStation.Contains(queryWorkTaskInfoDto.RouteInfo) || ri.ToStation.Contains(queryWorkTaskInfoDto.RouteInfo));


            exp.AndIF(queryWorkTaskInfoDto.Priority.HasValue, (wti, ri) => wti.Priority == queryWorkTaskInfoDto.Priority);
            exp.AndIF(queryWorkTaskInfoDto.CurrentDispatchType != 0, (wti, ri) => (int)wti.CurrentDispatchType == queryWorkTaskInfoDto.CurrentDispatchType);

            exp.AndIF(queryWorkTaskInfoDto.TaskProcessState.HasValue, (wti, ri) => wti.TaskProcessState == Enum.Parse<EnumTaskProcessState>(queryWorkTaskInfoDto.TaskProcessState.ToString()));

            exp.AndIF(queryWorkTaskInfoDto.TaskState.HasValue, (wti, ri) => wti.TaskState == Enum.Parse<EnumTaskState>(queryWorkTaskInfoDto.TaskState.ToString()));
            exp.AndIF(queryWorkTaskInfoDto.TaskType.HasValue, (wti, ri) => wti.TaskType == Enum.Parse<EnumTaskType>(queryWorkTaskInfoDto.TaskType.ToString()));

            exp.AndIF(queryWorkTaskInfoDto.FromSaveTime.HasValue && queryWorkTaskInfoDto.ToSaveTime.HasValue, (wti, ri) => wti.SaveTime >= queryWorkTaskInfoDto.FromSaveTime && wti.SaveTime < queryWorkTaskInfoDto.ToSaveTime);
            exp.AndIF(queryWorkTaskInfoDto.FromUpdateTime.HasValue && queryWorkTaskInfoDto.ToUpdateTime.HasValue, (wti, ri) => wti.UpdateTime >= queryWorkTaskInfoDto.FromUpdateTime && wti.UpdateTime < queryWorkTaskInfoDto.ToUpdateTime);

            exp.AndIF(queryWorkTaskInfoDto.WmsTaskCode.HasValue, (wti, ri) => wti.WmsTaskCode == queryWorkTaskInfoDto.WmsTaskCode);
            exp.AndIF(queryWorkTaskInfoDto.DependWmsTaskCode.HasValue, (wti, ri) => wti.DependWmsTaskCode == queryWorkTaskInfoDto.DependWmsTaskCode);
            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.WmsFromStation), (wti, ri) => wti.WmsFromStation.Contains(queryWorkTaskInfoDto.WmsFromStation));
            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.WmsFromPosition), (wti, ri) => wti.WmsFromPosition.ToString().Contains(queryWorkTaskInfoDto.WmsFromPosition));

            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.WmsToStation), (wti, ri) => wti.WmsToStation.Contains(queryWorkTaskInfoDto.WmsToStation));
            exp.AndIF(!string.IsNullOrEmpty(queryWorkTaskInfoDto.WmsToPosition), (wti, ri) => wti.WmsToPosition.Contains(queryWorkTaskInfoDto.WmsToPosition));

            PageDto<WCSWorkTaskInfoDto> pagedData = new PageDto<WCSWorkTaskInfoDto>();
            RefAsync<int> totalCount = 0;

            var result = await _WorkTaskInfoRepository.AsSugarClient()
                .Queryable<WorkTaskInfo, RouteInfo>((wti, ri) => new JoinQueryInfos(JoinType.Inner, wti.RouteID == ri.ID))
                .Where(exp.ToExpression())
                .OrderBy((wti, ri) => wti.SaveTime, OrderByType.Desc)
                .Select((wti, ri) => new WCSWorkTaskInfoDto()
                {
                    ID = wti.ID,
                    RouteID = wti.RouteID,
                    FromStation = ri.FromStation,
                    ToStation = ri.ToStation,
                    Priority = wti.Priority,
                    PalletCode = wti.PalletCode,
                    TaskCode = wti.TaskCode,
                    TaskProcessState = wti.TaskProcessState,
                    TaskState = wti.TaskState,
                    TaskType = wti.TaskType,
                    SaveTime = wti.SaveTime,
                    UpdateTime = wti.UpdateTime,
                    WmsTaskCode = wti.WmsTaskCode,
                    DependWmsTaskCode = wti.DependWmsTaskCode,
                    WmsFromStation = wti.WmsFromStation,
                    WmsFromPosition = wti.WmsFromPosition.ToString(),
                    WmsToStation = wti.WmsToStation,
                    WmsToPosition = wti.WmsToPosition,
                    CurrentRounteDetailID = wti.CurrentRounteDetailID,
                    CurrentDetailTaskState = wti.CurrentDetailTaskState,
                    CurrentDispatchType = wti.CurrentDispatchType,
                    CurrentFromEquipment = wti.CurrentFromEquipment,
                    CurrentFromCargo = wti.CurrentFromCargo,
                    CurrentToEquipment = wti.CurrentToEquipment,
                    CurrentToCargo = wti.CurrentToCargo,
                    CurrentCreateTime = wti.CurrentCreateTime,
                    CurrentUpdateTime = wti.CurrentUpdateTime,
                    UploadWmsState = wti.UploadWmsState,
                    UploadWmsTime = wti.UploadWmsTime
                })
                .ToPageListAsync(queryWorkTaskInfoDto.PageIndex, queryWorkTaskInfoDto.PageSize, totalCount);

            pagedData.Result = result;
            pagedData.Total = totalCount;

            return pagedData;
        }

        /// <summary>
        /// 删除托盘
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DelWorkTaskInfAsync(long id)
        {
            try
            {
                //查询任务数据
                var workTaskInfo = await _WorkTaskInfoRepository.GetByIdAsync(id);
                if (workTaskInfo != null)
                {
                    var historyInfo = _mapper.Map<WorkTaskInfo, HistoryWorkTaskInfo>(workTaskInfo);
                    try
                    {
                        _WorkTaskInfoRepository.AsSugarClient().AsTenant().BeginTran();

                        await _WorkTaskInfoRepository.AsSugarClient().Insertable(historyInfo).ExecuteCommandAsync();
                        await _WorkTaskInfoRepository.AsSugarClient().Deleteable(workTaskInfo).ExecuteCommandAsync();

                        _WorkTaskInfoRepository.AsSugarClient().AsTenant().CommitTran();
                        return true;
                    }
                    catch (Exception)
                    {
                        _WorkTaskInfoRepository.AsSugarClient().AsTenant().RollbackTran();
                        throw;
                    }
                }
                return false;
            }
            catch (Exception ex)
            {
                _LogUtil.Error($"删除任务报错ex={ex.ToString()}");
                throw;
            }
        }
        public async Task<WorkTaskInfo> GetWorkTaskInfoByIdAsync(long id)
        {
            var workTaskInfo = await _WorkTaskInfoRepository.GetByIdAsync(id);
            return workTaskInfo;
        }

        public async Task<bool> UpdataWorkTaskInfoByTask(WorkTaskInfo workTaskInfo)
        {
            return await _WorkTaskInfoRepository.UpdateAsync(workTaskInfo);
        }

        /// <summary>
        /// 模拟交互获取WMS任务
        /// </summary>
        /// <param name="containerBarcode"></param>
        /// <param name="equipment"></param>
        /// <returns></returns>
        public async Task<bool> GetWarehouseWMSTaskAsync(string containerBarcode, string equipment)
        {
            //向wms读取巷道分配任务
            WMSApiDomain.WebApi.HeaderResult<WmsTaskInfoDto> res = await WCSMessageWithWMSApi.WCSCreatUploadWarehouseWMSTaskAsync(containerBarcode, equipment);
            if (!res.IsSucceed && res.Result == null)
            {
                return false;
            }
            WmsTaskInfoDto workTaskDto = res.Result;
            //WorkTaskInfo数据补全
            var workTaskInfo = new WorkTaskInfo();

            long id = _Sonoflake.GetId();//雪花ID
            workTaskInfo.ID = id;
            //wcs任务code从wmstaskcode日开始截取
            int.TryParse(workTaskDto.TaskCode.ToString().Substring(6), out var wcsTaskCode);
            workTaskInfo.TaskCode = wcsTaskCode;
            //wms赋值
            workTaskInfo.WmsTaskCode = workTaskDto.TaskCode;
            workTaskInfo.DependWmsTaskCode = workTaskDto.DependWMSTaskCode;
            workTaskInfo.TaskType = Enum.Parse<EnumTaskType>(workTaskDto.TaskType.ToString());

            workTaskInfo.WmsFromPosition = workTaskDto.StartPosition;
            workTaskInfo.WmsToPosition = workTaskDto.EndPosition;
            workTaskInfo.WmsFromStation = workTaskDto.FromStation;
            workTaskInfo.WmsToStation = workTaskDto.ToStation;
            workTaskInfo.TaskProcessState = EnumTaskProcessState.Initial;
            workTaskInfo.TaskState = EnumTaskState.Executing;
            workTaskInfo.Priority = workTaskDto.Priority;

            //托盘条码
            workTaskInfo.PalletCode = containerBarcode.Trim();

            #region 任务子任务信息赋值by RouteDetailInfo
            //获取配置巷道信息
            var routeConfigExp = Expressionable.Create<RouteInfo>();
            routeConfigExp.AndIF(true, (a) => a.FromStation == workTaskInfo.WmsFromStation && a.ToStation == workTaskInfo.WmsToStation);
            var routeInfo = await _WorkTaskInfoRepository.AsSugarClient()
                .Queryable<RouteInfo>()
                .Where(routeConfigExp.ToExpression())
                .Select((a) => new RouteInfo()
                {
                    ID = a.ID,
                    FromStation = a.FromStation,
                    ToStation = a.ToStation,
                }).FirstAsync();
            if (routeInfo == null)
            {
                _LogUtil.Error($"模拟请求目标位：托盘【{containerBarcode}】请求目标位，PLC设备【{equipment}】起始工位{workTaskInfo.WmsFromStation}目标工位{workTaskInfo.WmsToStation}获取工位失败");
                return false;
            }

            //巷道详情信息获取
            var routeDetailConfigExp = Expressionable.Create<RouteDetailInfo>();
            routeDetailConfigExp.AndIF(true, (a) => a.RouteID == routeInfo.ID && a.IsStart);
            var routeDetailInfo = await _WorkTaskInfoRepository.AsSugarClient()
                .Queryable<RouteDetailInfo>()
                .Where(routeDetailConfigExp.ToExpression())
                .Select((a) => new
                {
                    a.ID,
                    a.RouteID,
                    a.FromCargo,
                    a.ToCargo,
                    a.DispatchType,
                    a.FromEquipment,
                    a.ToEquipment,

                }).FirstAsync();

            if (routeDetailInfo == null)
            {
                //runLogInfo.RunLog = $"巷道路径详情配置信息起始工位{workTaskInfo.WmsFromStation}目标工位{workTaskInfo.WmsToStation}获取设备路径失败";
                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                _LogUtil.Error($"模拟请求目标位：托盘【{containerBarcode}】请求目标位，PLC设备【{equipment}】起始工位{workTaskInfo.WmsFromStation}目标工位{workTaskInfo.WmsToStation}获取设备路径失败");
                return false;
            }

            workTaskInfo.CurrentToEquipment = routeDetailInfo.ToEquipment;


            workTaskInfo.CurrentFromCargo = routeDetailInfo.FromCargo;
            workTaskInfo.CurrentToCargo = routeDetailInfo.ToCargo;
            workTaskInfo.RouteID = routeDetailInfo.RouteID;
            workTaskInfo.CurrentRounteDetailID = routeDetailInfo.ID;
            workTaskInfo.CurrentDispatchType = routeDetailInfo.DispatchType;
            //起始设备位 
            workTaskInfo.CurrentFromEquipment = workTaskInfo.WmsFromPosition; //WMS 作业实际起点设备
                                                                              // workTaskInfo.CurrentToEquipment = routeDetailInfo.ToEquipment;
            workTaskInfo.CurrentDetailTaskState = EnumDetailTaskState.Executing;
            workTaskInfo.CurrentCreateTime = DateTime.Now;
            workTaskInfo.CurrentUpdateTime = DateTime.Now;
            #endregion

            workTaskInfo.SaveTime = DateTime.Now;
            workTaskInfo.UpdateTime = DateTime.Now;


            try
            {
                //同步更新wms任务状态为执行中
                var flag = await WCSMessageWithWMSApi.WCSUpdateWMStaskStateAndProcessTaskStateAsync(workTaskInfo.WmsTaskCode, (int)EnumTaskState.Executing);
                if (flag)
                {
                    workTaskInfo.UploadWmsState = EnumUploadWmsState.Succeed;
                    workTaskInfo.UploadWmsTime = DateTime.Now;
                }
                else
                {
                    workTaskInfo.UploadWmsState = EnumUploadWmsState.Failed;
                    workTaskInfo.UploadWmsTime = DateTime.Now;
                }
                _LogUtil.Debug($"模拟请求目标位：托盘【{containerBarcode}】请求目标位，PLC设备【{equipment}】 任务号：{workTaskInfo.WmsTaskCode}上报WMS状态 {flag}");
            }
            catch (Exception ex)
            {
                //runLogInfo.RunLog = $"任务号{workTaskInfo.WmsTaskCode}:向Wms同步状态更新失败";

                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                _LogUtil.Error($"模拟请求目标位：托盘【{containerBarcode}】请求目标位，PLC设备【{equipment}】任务号{workTaskInfo.WmsTaskCode}:向Wms同步状态更新失败，报错 ex={ex.Message}");
                return false;
            }

            //WorkTaskInfo数据插入
            var expCheck = Expressionable.Create<WorkTaskInfo>();
            expCheck.AndIF(true, (a) => a.PalletCode == containerBarcode && (a.TaskState == EnumTaskState.Initial || a.TaskState == EnumTaskState.Executing));
            var wcsCheckWorkTaskInfo = await _WorkTaskInfoRepository.GetFirstAsync(expCheck.ToExpression());
            if (wcsCheckWorkTaskInfo == null)
            {
                bool bl = await _WorkTaskInfoRepository.InsertAsync(workTaskInfo);
            }

            //查询重复任务 
            var taskList = await _WorkTaskInfoRepository.AsSugarClient().Queryable<WorkTaskInfo>()
                .Where(t => t.PalletCode == workTaskInfo.PalletCode
                            && t.TaskState == workTaskInfo.TaskState
                            && t.RouteID == workTaskInfo.RouteID
                            && t.CurrentRounteDetailID == workTaskInfo.CurrentRounteDetailID)
                .ToListAsync();
            //两条相同任务以上就只保留一条
            if (taskList.Count > 1)
            {
                var tempTaskList = taskList.Remove(taskList[0]);
                if (tempTaskList)
                {
                    await _WorkTaskInfoRepository.AsSugarClient().Deleteable(taskList).ExecuteCommandAsync();
                    _LogUtil.Debug($"模拟请求目标位：托盘【{containerBarcode}】请求目标位，PLC设备【{equipment}】删除重复任务数： {taskList.Count}, 任务号：{workTaskInfo.WmsTaskCode}");
                }
            }
            return true;
        }
    }
}
